use crate::client::connection_pool::{ConnectionPool, PoolError};
use crate::client::error::GrpcClientError;
use crate::client::load_balancer::LoadBalancer;
use crate::client::retry_executor::RetryExecutor;
use crate::client::retry_policy::RetryPolicy;
use anyhow::Result;
use std::future::Future;
use std::pin::Pin;
use std::sync::Arc;
use tonic::transport::Channel;
use tonic::Status;

pub mod auth_service {
    tonic::include_proto!("auth_service");
}

pub mod user_service {
    tonic::include_proto!("user_service");
}

use auth_service::{
    auth_service_client::AuthServiceClient,
};

use user_service::{user_service_client::UserServiceClient};


pub trait GrpcClient: Sized + Send + Sync {
    fn from_channel(channel: Channel) -> Self;
}

pub struct ClientManager {
    pool: Arc<ConnectionPool>,
    load_balancer: Arc<LoadBalancer>,
    retry_executor: RetryExecutor,
}

impl ClientManager {
    pub fn new(pool: ConnectionPool, load_balancer: LoadBalancer) -> Self {
        let retry_policy = RetryPolicy::default();
        let retry_executor = RetryExecutor::new(retry_policy.clone());

        Self {
            pool: Arc::new(pool),
            load_balancer: Arc::new(load_balancer),
            retry_executor,
        }
    }

    pub async fn create_client_with_retry<T: GrpcClient>(
        &self,
        service_name: &str,
    ) -> Result<T, PoolError> {
        let service_name = service_name.to_string();
        let pool = Arc::clone(&self.pool);

        // 修复类型注解和闭包结构
        let operation = move || -> Pin<Box<dyn Future<Output = Result<T, GrpcClientError>>>> {
            let service_name = service_name.clone();
            let pool = Arc::clone(&pool);

            Box::pin(async move {
                let channel = pool
                    .get_connection(&service_name)
                    .await
                    .map_err(|e| GrpcClientError::Pool(e))?;
                Ok(T::from_channel(channel))
            })
        };

        self.retry_executor
            .execute_with_retry(operation)
            .await
            .map_err(|e| PoolError::RetryFailed(e.to_string()))
    }

    pub async fn create_client<T: GrpcClient>(&self, service_name: &str) -> Result<T, PoolError> {
        let channel = self.pool.get_connection(service_name).await?;
        Ok(T::from_channel(channel))
    }

    // pub async fn get_user_client_with_retry(
    //     &self,
    // ) -> Result<UserServiceClient<Channel>, PoolError> {
    //     self.create_client_with_retry("user_service").await
    // }
    //
    // pub async fn get_auth_client_with_retry(
    //     &self,
    // ) -> Result<AuthServiceClient<Channel>, PoolError> {
    //     self.create_client_with_retry("auth_service").await
    // }
    //
    // pub async fn get_user_client(&self) -> Result<UserServiceClient<Channel>, PoolError> {
    //     self.create_client("user_service").await
    // }
    //
    // pub async fn get_auth_client(&self) -> Result<AuthServiceClient<Channel>, PoolError> {
    //     self.create_client("auth_service").await
    // }

    pub async fn execute_rpc_with_retry<F, T>(
        &self,
        client: &mut T,
        rpc_call: F,
    ) -> Result<T, GrpcClientError>
    where
        F: Fn() -> Pin<Box<dyn Future<Output = Result<T, Status>>>>,
    {
        self.retry_executor.execute_with_retry(|| rpc_call()).await
    }
}

// impl GrpcClient for AuthServiceClient<Channel> {
//     fn from_channel(channel: Channel) -> Self {
//         Self::new(channel)
//     }
// }
//
// impl GrpcClient for UserServiceClient<Channel> {
//     fn from_channel(channel: Channel) -> Self {
//         Self::new(channel)
//     }
// }
